#ifndef __UDP_SERVER_HPP__
#define _UDP_SERVER_HPP__

#include <iostream>
#include <memory>
#include <cstring>
#include <string>
#include <sys/types.h>          
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <functional>

#include "Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"

using namespace LogModule;

const static uint16_t gdefaultport=8080;
const static std::string gdefaultip="127.0.0.1";//表示本地主机
const static int gsockfd=-1;
using func_t =std::function<std::string(const std::string&)>;

class Udpserver
{
public:
    Udpserver(func_t func, uint16_t port=gdefaultport) 
    :_sockfd(gsockfd),
    _addr(port),
    _isrunning(false),
    _func(func)
    {}

    void InitServer()
    {
        //1.创建socket
        _sockfd=::socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd<0)
        {
            LOG(LogLevel::FATAL)<<"socket:"<<strerror(errno);
            Die(SOCKET_ERR);
        }
        LOG(LogLevel::INFO)<<"socket sucess,sockfd is: "<<_sockfd;

        //2.填充网络信息
        // struct sockaddr_in local;
        // bzero(&local,sizeof(local));
        // local.sin_family=AF_INET;
        // local.sin_port=::htons(_port);
        // //local.sin_addr.s_addr=::inet_addr(_ip.c_str());//string ip->4bytes 2.转换为网络序列 network order
        // local.sin_addr.s_addr=INADDR_ANY;

        //2.1设置进入内核中  bind
        //int n=::bind(_sockfd,CONV(&local),sizeof(local));
        int n=::bind(_sockfd,_addr.NetAddr(),_addr.NetAddrLen());
        if(n<0)
        {
            LOG(LogLevel::FATAL)<<"bind: "<<strerror(errno);
            Die(BIND_ERR);
        }
        LOG(LogLevel::INFO)<<"bind sucess";

    }
    void Start()
    {
        _isrunning=true;
        while(true)
        {
            //通过recvfrom接受消息
            char inbuffer[1024];
            struct sockaddr_in peer;
            socklen_t len=sizeof(peer);

            ssize_t n=::recvfrom(_sockfd,inbuffer,sizeof(inbuffer)-1,0,CONV(&peer),&len);
            if(n>0)
            {
                //消息内容和谁转发的
                // uint16_t clientport=::ntohs(peer.sin_port);
                // std::string clientip=::inet_ntoa(peer.sin_addr);

                // InetAddr cli(peer);
                // inbuffer[n]=0;

                // //std::string clientinfo=clientip+std::to_string(clientport)+'#'+inbuffer;
                // std::string clientinfo=cli.Ip()+std::to_string(cli.Port())+'#'+inbuffer;
                // LOG(LogLevel::DEBUG)<<clientinfo;

                // //发送回去 sendto
                // std::string echo_string="echo# ";
                // echo_string+=inbuffer;

                // ::sendto(_sockfd,echo_string.c_str(),echo_string.size(),0,CONV(&peer),sizeof(peer));

                //把英文单词转换为中文
                inbuffer[n]=0;
                std::string result=_func(inbuffer);//回调函数
                ::sendto(_sockfd,result.c_str(),result.size(),0,CONV(&peer),sizeof(peer));
            }
        }
        _isrunning=false;
    }
    ~Udpserver() 
    {
        if(_sockfd>gsockfd)
            ::close(_sockfd);
    }  
private:
    int _sockfd;
    //uint16_t _port;//服务器对应的端口号
    // std::string _ip;//服务器所对应的ip
    InetAddr _addr;
    bool _isrunning;//服务器的运行状态

    func_t _func;//回调函数，执行业务
};
#endif